
#include <BCube>
#include <BSurface>
#include <BGridPlane>
#include <BFileDialog>
#include <BReadWrite>
#include <BScrollWidget>
#include <BApplication>

#include "BasicSampleHandler.h"
#include "TerrainSampleHandler.h"
#include "SupportVertexHandler.h"
#include "PushHandler.h"
#include "FixedHandler.h"
#include "GearHandler.h"
#include "PointHandler.h"
#include "HingeHandler.h"
#include "SliderHandler.h"
#include "ConearHandler.h"
#include "SixdofHandler.h"
#include "StripeSliderHandler.h"
#include "CurveSliderHandler.h"
#include "MainWindow.h"

MainWindow::MainWindow()
{
	_mainHandler = new MainHandler();

	_scene = new BScene();
	{
		//BSurface* surface = new BSurface(200, 200, 10, 10);
		//surface->setOrientation(Orientation_Vertical);
		//surface->setPolyMode(Poly_Line);
		//surface->setColor(255, 130, 60);
		//surface->setLighting(false);
		//surface->setPosition(-100, -100, 0);
		//_scene->insert(surface);
		//_mainHandler->setGridSurface(surface);

		BBody* groundBody = new BBody("Ground");
		groundBody->setRestitution(1);
		{
			BGridPlane* gridPlane = new BGridPlane(BVector(0, 0, 1), 0);
			gridPlane->setGridSize(100);
			gridPlane->setVerticalSegments(10);
			gridPlane->setHorizontalSegments(10);
			gridPlane->setLighting(false);
			gridPlane->setColor(200, 200, 200);
			groundBody->insertShape(gridPlane);

			//BCube* cube = new BCube(100, 100, 1, 20, 20);
			//cube->setPolyMode(Poly_Line);
			//groundBody->insertShape(cube);
		}
		_scene->insert(groundBody);

	}

	BCamera* camera = new BCamera();
	camera->setPosition(0, -16, 0);
	camera->setCenter(0, 0, 0);
	camera->setFovy(36);
	camera->setNear(BReal(0.1));
	camera->setFar(1000);
	camera->setColor(30, 40, 50);

	_treeWidget = new BTreeWidget();
	{
		BTreeItem* samplesItem = _treeWidget->addItem("Samples");
		samplesItem->addChild("Basics")->setAsset(new BasicSampleHandler);
		samplesItem->addChild("Terrain")->setAsset(new TerrainSampleHandler);
		samplesItem->addChild("Support")->setAsset(new SupportVertexHandler);
		samplesItem->addChild("Push")->setAsset(new PushHandler);

		BTreeItem* item = _treeWidget->addItem("Restraints");
		item->addChild("Fixed")->setAsset(new FixedHandler);
		item->addChild("Point")->setAsset(new PointHandler);
		item->addChild("Hinge")->setAsset(new HingeHandler);
		item->addChild("Slider")->setAsset(new SliderHandler);
		item->addChild("Conear")->setAsset(new ConearHandler);
		item->addChild("Sixdof")->setAsset(new SixdofHandler);
		item->addChild("Gear")->setAsset(new GearHandler);
		item->addChild("Stripe")->setAsset(new StripeSliderHandler);
		item->addChild("Curve")->setAsset(new CurveSliderHandler);
	}

	_viewer = new BViewer();
	_viewer->setScene(_scene);
	_viewer->setCamera(camera);
	_viewer->setHandler(_mainHandler);
	{
		_dockLayout = new BDockLayout(_viewer);
	}

	BVBoxLayout* rightLayout = new BVBoxLayout();
	{
		BScrollWidget* scrollWidget = new BScrollWidget();
		scrollWidget->setAreaPolicy(Policy_Growing, Policy_Preferred);
		{
			_bodyBoard = new BodyBoard();
			_bodyBoard->setHeightPolicy(Policy_Preferred);

			_shapeBoard = new ShapeBoard();
			_shapeBoard->setHeightPolicy(Policy_Preferred);

			_restraintBoard = new RestraintBoard();
			_restraintBoard->setHeightPolicy(Policy_Preferred);

			scrollWidget->addWidget(_bodyBoard, Align_TopCenter);
			scrollWidget->addWidget(_shapeBoard, Align_TopCenter);
			scrollWidget->addWidget(_restraintBoard, Align_TopCenter);
		}

		_panelLayout = new BVBoxLayout();

		BGroupBox* optionsGroupBox = new BGroupBox("Options");
		{
			_dragImpulseSpinBox = new BFloatSpinBox();
			_dragImpulseSpinBox->setPrefix("Drag-Impuse : ");

			_signSleepsCheckBox = new BCheckBox("Sign Sleeping Bodys");
			_showContactsCheckBox = new BCheckBox("Show Contacts");
			_onlyDynamicBodyCheckBox = new BCheckBox("Only Dynamic Bodys");
			BVBoxLayout* vlayout = new BVBoxLayout(optionsGroupBox);
			vlayout->addWidget(_dragImpulseSpinBox);
			vlayout->addWidget(_signSleepsCheckBox);
			vlayout->addWidget(_showContactsCheckBox);
			vlayout->addWidget(_onlyDynamicBodyCheckBox);
		}

		BGridLayout* infoLayout = new BGridLayout();
		{
			_broadphaseInfoSpinBox = new BSpinBox();
			_broadphaseInfoSpinBox->setReadOnly(true);

			_manifoldCountSpinBox = new BSpinBox();
			_manifoldCountSpinBox->setReadOnly(true);

			_realFreqencySpinBox = new BSpinBox();
			_realFreqencySpinBox->setSuffix("fps");
			_realFreqencySpinBox->setReadOnly(true);

			infoLayout->addWidget(0, 0, new BLabel("overlap-count:"));
			infoLayout->addWidget(0, 1, _broadphaseInfoSpinBox);
			infoLayout->addWidget(1, 0, new BLabel("manifold-count"));
			infoLayout->addWidget(1, 1, _manifoldCountSpinBox);
			infoLayout->addWidget(2, 0, new BLabel("real-freqency:"));
			infoLayout->addWidget(2, 1, _realFreqencySpinBox);
			infoLayout->setColumnStretch(0, 0);
		}

		rightLayout->addWidget(scrollWidget, 999);
		rightLayout->addLayout(_panelLayout);
		rightLayout->addWidget(optionsGroupBox);
		rightLayout->addLayout(infoLayout);
	}

	BHBoxLayout* splitter = new BHBoxLayout();
	splitter->setSpacing(5);
	splitter->setSplitable(true);
	splitter->addWidget(_treeWidget, 1);
	splitter->addWidget(_viewer, 10);
	splitter->addLayout(rightLayout);

	BHBoxLayout* bottomLayout = new BHBoxLayout();
	{
		_resetButton = new BButton("reset");
		_startButton = new BButton();
		_startButton->setText("start", false);
		_startButton->setText("pause", true);
		_startButton->setCheckable(true);
		_timeSpinBox = new BRealSpinBox();
		_timeSpinBox->setDecimals(3);
		_timeSpinBox->setSuffix("s");
		_timeSpinBox->setSuffixAlign(Align_RightCenter);

		bottomLayout->addSpring(10);
		bottomLayout->addWidget(_resetButton);
		bottomLayout->addWidget(_startButton);
		bottomLayout->addSpacer(10);
		bottomLayout->addWidget(new BLabel("time:"), 0);
		bottomLayout->addWidget(_timeSpinBox);
		bottomLayout->addSpring(10);
	}

	BVBoxLayout* vlayout = new BVBoxLayout(this);
	vlayout->addLayout(splitter);
	vlayout->addLayout(bottomLayout, 0);

	connect(_scene, Signal_Updated, &MainWindow::slotSceneUpdated);
	connect(_scene, Signal_Paused, &MainWindow::slotScenePaused);

	connect(_resetButton, Signal_Clicked, &MainWindow::slotResetButtonClicked);
	connect(_startButton, Signal_Toggled, &MainWindow::slotPauseButtonToggled);
	connect(_treeWidget, Signal_ItemDoubleClicked, &MainWindow::slotTreeItemDoubleClicked);

	connect(_dragImpulseSpinBox, Signal_EditFinished, &MainWindow::slotDragImpulseEditFinished);
	connect(_signSleepsCheckBox, Signal_Toggled, &MainWindow::slotSignSleepsCheckBoxToggled);
	connect(_showContactsCheckBox, Signal_Toggled, &MainWindow::slotShowContactsCheckBoxToggled);
	connect(_onlyDynamicBodyCheckBox, Signal_Toggled, &MainWindow::slotOnlyDynamicsCheckBoxToggled);

	connect("append-panel", &MainWindow::slotAppendPanel);
	connect("remove-panel", &MainWindow::slotRemovePanel);
	connect("edit-node", &MainWindow::slotEditNode);
	connect("edit-shape", &MainWindow::slotEditShape);
	connect("edit-restraint", &MainWindow::slotEditRestraint);
	connect("show-note", &MainWindow::slotShowNote);
	connect("hide-note", &MainWindow::slotHideNote);

	_dragImpulseSpinBox->setValue((float)_mainHandler->dragImpulse());
	_scene->start();
}

void MainWindow::slotSceneUpdated(BScene* scene, const BValue& value)
{
	_timeSpinBox->setValue(value);
}
void MainWindow::slotScenePaused(BScene* scene, const BValue& value)
{
	if (value)
	{
		_startButton->setChecked(false);
	}
	else
	{
		_startButton->setChecked(true);
	}
	_timeSpinBox->setValue(scene->time());
}

void MainWindow::slotResetButtonClicked(BObject* object, const BValue& value)
{
	_viewer->scene()->reset();
}
void MainWindow::slotPauseButtonToggled(BObject* object, const BValue& value)
{
	if (bool checked = value)
		_viewer->scene()->start();
	else
		_viewer->scene()->pause();
}
void MainWindow::slotTreeItemDoubleClicked(BObject* object, const BValue& value)
{
	BTreeItem* item = value;
	_mainHandler->clearChildren();
	if (BHandler* handler = item->asset())
	{
		_mainHandler->addChild(handler);
	}
}

void MainWindow::slotAppendPanel(BObject* object, const BValue& value)
{
	BWidget* widget = value;
	_panelLayout->addWidget(widget);
}
void MainWindow::slotRemovePanel(BObject* object, const BValue& value)
{
	BWidget* widget = value;
	_panelLayout->remove(widget);
}
void MainWindow::slotEditNode(BObject* object, const BValue& value)
{
	_bodyBoard->setAsset(value);
}
void MainWindow::slotEditShape(BObject* object, const BValue& value)
{
	_shapeBoard->setAsset(value);
}
void MainWindow::slotEditRestraint(BObject* object, const BValue& value)
{
	_restraintBoard->setAsset(value);
}
void MainWindow::slotShowNote(BObject* object, const BValue& value)
{
	if (BLayout* layout = value)
	{
		_dockLayout->addLayout(layout, Align_RightBottom);
	}
	if (BWidget* widget = value)
	{
		_dockLayout->addWidget(widget, Align_RightBottom);
	}
}
void MainWindow::slotHideNote(BObject* object, const BValue& value)
{
	if (BLayout* layout = value)
	{
		_dockLayout->remove(layout);
	}
	if (BWidget* widget = value)
	{
		_dockLayout->remove(widget);
	}
}

void MainWindow::slotDragImpulseEditFinished(BObject* object, const BValue& value)
{
	float dragImpulse = value;
	_mainHandler->setDragImpulse(dragImpulse);
}
void MainWindow::slotSignSleepsCheckBoxToggled(BObject* object, const BValue& value)
{
	bool checked = value;
	_mainHandler->showSleeps(checked);
}
void MainWindow::slotShowContactsCheckBoxToggled(BObject* object, const BValue& value)
{
	bool checked = value;
	_mainHandler->showContacts(checked);
}
void MainWindow::slotOnlyDynamicsCheckBoxToggled(BObject* object, const BValue& value)
{
	bool checked = value;
	_mainHandler->showOnlyDynamicBodys(checked);
}

void MainWindow::showEvent(const BEvent& event)
{
	BMainWindow::showEvent(event);
	BRoundHandler* handler = (BRoundHandler*)_viewer->handler();
	handler->focus();
}

void MainWindow::updateEvent(const BEvent& event)
{
	int realFrequency = BApplication::realFrequency();
	_realFreqencySpinBox->setValue(realFrequency);
}

void MainWindow::styleEvent(const BEvent& event)
{
	BMainWindow::styleEvent(event);
	const BStyle* style = event.value();
	_resetButton->setIcon(style->icon("reset"));
	_startButton->setIcon(style->icon("start"));
}
